#ifndef __settings_kenny_dkfjiwoo3w3__
#define __settings_kenny_dkfjiwoo3w3__

#include <cstdio>

#include <hude/base/base_type.hpp>
#include <hude/base/log.hpp>
#include <hude/utils/json.hpp>

namespace ha
{
    using json_t = hude::utils::json_t;

    /*********************************************************************
     * @brief 全局设置
     */
    class settings_t
    {
    public:
        static settings_t& global();

        bool update( const char* path );
        std::string dump() const { return root_.dump(); }

        json_t* operator->() { return &root_; }
        const json_t* operator->() const { return &root_; }

        json_t& operator*() { return root_; }
        const json_t& operator*() const { return root_; }

        json_t::reference operator[]( const json_t::object_t::key_type& key ) { return root_.at( key ); }
        json_t::const_reference operator[]( const json_t::object_t::key_type& key ) const { return root_.at( key ); }

    private:
        settings_t() {}
        ~settings_t() {}
        settings_t( const settings_t& ) = delete;
        settings_t& operator=( const settings_t& );

        void set_default();

    private:
        json_t root_;

    };

    /*********************************************************************
     * @brief 按给定文件更新设置，该更新行为应用文件中的所有设置项对当前设置进行局部更新，
     *          也就是保留当前设置存在而文件中缺少的设置项。
     */
    inline bool settings_t::update( const char* path )
    {
        std::string content;

        {
            auto fp = fopen( path, "rb" );
            if( ! fp )
            {
                llog_err( "<app>", "error: open settings file %s", path );
                return false;
            }

            fseek( fp, 0, SEEK_END );

            auto siz = ftell( fp );

            content.resize( siz );

            rewind( fp );

            int r = fread( &(content[0]), sizeof(char), siz, fp );

            fclose( fp );

            if( r < 0 && r != (int)siz )
            {
                llog_err( "<app>", "error: read settings file size: %d", r );
                return false;
            }
        }

        auto change = json_t::parse( content.c_str() );

        root_.merge_patch( change );

        return true;
    }

    /*********************************************************************
     * @brief 获取全局设置
     */
    inline settings_t& settings_t::global()
    {
        auto initer = []() -> settings_t*
        {
            auto p = new settings_t;
            p->set_default();
            return p;
        };

        static settings_t* g = initer();

        return *g;
    }

    /*********************************************************************
     * @brief 恢复默认设置
     */
    inline void settings_t::set_default()
    {
        std::string def{ R"(
            {
                "units": {
                    "shell": {
                        "enable": false,
                        "group": "0x9a",
                        "elements": [
                            {
                                "module": "pty",
                                "args": {
                                    "link": "/tmp/dev/ttySH"
                                },
                                "peer": { "tx": 1, "rx": 2 }
                            },
                            {
                                "module": "shell",
                                "args": {
                                    "cmd": "sh",
                                    "args": ["ls"]
                                },
                                "peer": { "tx": 2, "rx": 1 }
                            }
                        ]
                    },
                    "led-rgb": {
                        "enable": false,
                        "group": 1,
                        "elements": [
                            {
                                "module": "pty",
                                "args": {
                                    "link": "/tmp/dev/ttyLED"
                                },
                                "peer": { "tx": 1, "rx": 2 }
                            },
                            {
                                "module": "gpio",
                                "args": {},
                                "peer": { "tx": 2, "rx": 1 }
                            }
                        ]
                    },
                    "gpio": {
                        "enable": false,
                        "group": 2,
                        "elements": [
                            {
                                "module": "pty",
                                "args": {
                                    "link": "/tmp/dev/ttyGPIO"
                                },
                                "peer": { "tx": 1, "rx": 2 }
                            },
                            {
                                "module": "gpio",
                                "args": {},
                                "peer": { "tx": 2, "rx": 1 }
                            }
                        ]
                    },
                    "gps": {
                        "enable": false,
                        "group": 3,
                        "elements": [
                            {
                                "module": "pty",
                                "args": {
                                    "link": "/tmp/dev/ttyGPS"
                                },
                                "peer": { "tx": 1, "rx": 2 }
                            },
                            {
                                "module": "gps",
                                "args": "gps-lbs",
                                "peer": { "tx": 2, "rx": 1 }
                            }
                        ]
                    },
                    "uhf": {
                        "enable": true,
                        "group": 4,
                        "elements": [
                            {
                                "module": "pty",
                                "args": {
                                    "link": "/tmp/dev/ttyUHF"
                                },
                                "peer": { "tx": 1, "rx": 2 }
                            },
                            {
                                "module": "x2000",
                                "args": "rfid-turn",
                                "peer": { "tx": 2, "rx": 1 }
                            }
                        ]
                    },
                    "sport": {
                        "enable": false,
                        "group": 5,
                        "elements": [
                            {
                                "module": "pty",
                                "args": {
                                    "link": "/tmp/dev/ttySPORT"
                                },
                                "peer": { "tx": 1, "rx": 2 }
                            },
                            {
                                "module": "uart",
                                "args": {
                                    "name": "/dev/ttyACM0",
                                    "baud": 57600
                                },
                                "peer": { "tx": 2, "rx": 1 }
                            }
                        ]
                    },
                    "echo": {
                        "enable": false,
                        "group": 6,
                        "elements": [
                            {
                                "module": "pty",
                                "args": {
                                    "link": "/tmp/dev/ttyECHO"
                                },
                                "peer": { "tx": 1, "rx": 2 }
                            },
                            {
                                "module": "echo",
                                "args": {
                                },
                                "peer": { "tx": 2, "rx": 1 }
                            }
                        ]
                    }
                },
                "bricks": {
                    "gpio": {
                        "type": "lib",
                        "load": "./build-debug/lib/libvirt-gpio.so"
                    },
                    "x2000": {
                        "type": "lib",
                        "load": "./build-debug/lib/libvirt-x2000.so"
                    },
                    "ble": {
                        "type": "lib",
                        "load": "./build-debug/lib/libvirt-gatt.so"
                    },
                    "gps": {
                        "type": "lib",
                        "load": "./build-debug/lib/libvirt-gps.so"
                    },
                    "echo": {
                        "type": "lib",
                        "load": "$(std)/echo"
                    },
                    "uart": {
                        "type": "lib",
                        "load": "$(std)/uart"
                    },
                    "pty": {
                        "type": "lib",
                        "load": "$(std)/pty"
                    },
                    "shell": {
                        "type": "lib",
                        "load": "$(std)/shell"
                    }
                },
                "configs": {
                    "gpio-pins": {
                        "pins": [ 1, 2, 3 ]
                    },
                    "gps-lbs": {
                        "interval": 10000,
                        "gps": [
                            "$GNRMC,065004.00,A,2309.41232,N,11331.31714,E,0.024,170720,A63",
                            "$GNVTG,T,M,0.024,N,0.044,K,A3B",
                            "$GNGGA,065004.00,2309.41232,N,11331.31714,E,1,09,0.77,115.4,M,-4.8,M,53",
                            "$GNGSA,A,3,12,06,25,17,02,05,19,13,09,1.71,0.77,1.531C",
                            "$GPGSV,3,1,09,02,47,345,35,05,58,260,21,06,41,042,29,09,24,056,2971",
                            "$GPGSV,3,2,09,12,34,280,23,13,14,182,13,17,35,130,38,19,53,118,3975",
                            "$GPGSV,3,3,09,25,13,306,2042",
                            "$GNGLL,2309.41232,N,11331.31714,E,065004.00,A,A7F"
                        ]
                    },
                    "rfid-one": {
                        "rfid": [
                            { "ant": 255, "rand": 100, "ch": 3, "id": "FFFFFFAAFFAAFFFF" }
                        ]
                    },
                    "rfid-turn": {
                        "rfid": [
                            { "ant": 0, "rand": 50, "ch": 1, "id": "e2801170200004f370860998" },
                            { "ant": 0, "rand": 50, "ch": 2, "id": "e28011702000000270a10998" },
                            { "ant": 0, "rand": 50, "ch": 3, "id": "e28011052000791be7cf0aa9" },
                            { "ant": 0, "rand": 50, "ch": 4, "id": "e28011702000116dd1bc09e8" },

                            { "ant": 0, "rand": 50, "ch": 1, "id": "e2801170200004c270cc0998" },
                            { "ant": 0, "rand": 50, "ch": 2, "id": "e28011052000769ee9900aa9" },
                            { "ant": 0, "rand": 50, "ch": 3, "id": "e28011700000020cc38638c2" },
                            { "ant": 0, "rand": 50, "ch": 4, "id": "e28011052000751be9eb0aa9" },

                            { "ant": 0, "rand": 50, "ch": 1, "id": "e28011700000020f468de16d" },
                            { "ant": 0, "rand": 50, "ch": 2, "id": "e28011052000791be7cf0aa9" },
                            { "ant": 0, "rand": 50, "ch": 3, "id": "e2801170200004f370860998" },
                            { "ant": 0, "rand": 50, "ch": 4, "id": "e28011052000748ce9840aa9" },

                            { "ant": 0, "rand": 50, "ch": 1, "id": "e2801170200004c370860998" },
                            { "ant": 0, "rand": 50, "ch": 2, "id": "e28011602000613e17480a4d" },
                            { "ant": 0, "rand": 50, "ch": 3, "id": "e28011602000712e17480a4d" },
                            { "ant": 0, "rand": 50, "ch": 4, "id": "e280117020001003708a0998" },

                            { "ant": 1, "rand": 80, "ch": 1, "id": "e2801170200004f370860998" },
                            { "ant": 2, "rand": 80, "ch": 1, "id": "e2801170200014b370860998" },
                            { "ant": 3, "rand": 80, "ch": 1, "id": "e2801105200076d9e7d90aa9" },

                            { "ant": 255, "rand": 80, "ch": 9, "id": "e2801160200075ae174d0a4d" }
                        ]
                    },
                    "rfid-rand": {
                        "modu": "rand",
                        "id": []
                    }
                },
                "type": "root",
                "version": "1"
            }
        )" };

        root_ = json_t::parse( def );
    }
} //namespace ha

#endif //__settings_kenny_dkfjiwoo3w3__

